/* Request ID: 3631be47e51af91b8d275e0c763d07aa (05/18/2024 2:46pm) (minifier disabled) (PclBEsIgDAXQq3SnM7bJgVw4CL+CEwITQrm+O9/28RWM11rcoXrotFH0cyRcJOXCykFACuc+31LiK3sV/g97RgXHZuARrXQffFpThyb6jn27PVKLs0KdpMXgpSllw0mGLiHivm/PHw==) */ /*global grecaptcha:true */ (function($, LW) { // lib functions specific to frontend LW.lib = LW.lib || {}; var $body = $('body'); LW.lib.getICalDate = function(ts) { var dt; if (!ts) return ''; dt = new LW.lib.LWCDate(ts, 0); return dt.getFormattedDate('Ymd') + 'T' + dt.getFormattedDate('His') + 'Z'; }; // data props: ts_start, ts_end, is_all_day, title, summary, location LW.lib.getAddToGoogleLink = function(data) { var lnk = 'http://www.google.com/calendar/event?action=TEMPLATE&', args = [], sdate = this.getICalDate(data.ts_start), ts_end, edate; // google requires an end time, so use a sensible value if no data.ts_end if (data.ts_end) { ts_end = data.ts_end; } else { ts_end = (data.is_all_day) ? data.ts_start + 3600 * 24 : data.ts_start + 3600; } edate = this.getICalDate(ts_end); args.push('text=' + encodeURIComponent(data.title)); args.push('dates=' + sdate + '/' + edate); if (data.summary) { args.push('details=' + encodeURIComponent(LW.lib.htmlDecode(data.summary))); } if (data.location) { args.push('location=' + encodeURIComponent(data.location)); } return lnk + args.join('&') + '&trp=false&sprop=&sprop=name:'; }; // docs here: // https://docs.google.com/a/ikemcg.com/document/d/1scDk4WxGzDSGAF6OWiRkKwdQg9zD8kDReTH9cvTZnVo/edit LW.lib.getAddToYahooLink = function(data) { var lnk = 'http://calendar.yahoo.com/?v=60&view=d&type=20&', args = []; args.push('title=' + encodeURIComponent(data.title)); args.push('st=' + this.getICalDate(data.ts_start)); if (data.ts_end) { // using ET doesn't appear to work - Yahoo doesn't apply a local time shift, even with the Z args.push('et=' + this.getICalDate(data.ts_end)); } if (data.summary) { args.push('desc=' + encodeURIComponent(LW.lib.htmlDecode(data.summary))); } if (data.location) { args.push('in_loc=' + encodeURIComponent(data.location)); } return lnk + args.join('&'); }; // add frontend-specific plugins $.fn.extend({ // initialize all frontend behavior within a specific region. This plugin is called on the entire // page content on page load, and on each editable region when editing stops - on save or cancel initFrontendRegion: function() { return this.each(function() { var $region = $(this); var process = { // look up anything that needs JS processing captcha: { elements: $region.find('.lw_captcha') } }; $.each(process, function(fn, data) { // with each if (data.elements.length) { // if there are elements data.elements[fn](data.settings); // apply the function } }); // show image captions $region.find('.lw_image[data-caption-enabled="true"][data-caption]').each(function() { var $this = $(this), $sibling = ($this.parent().hasClass('lw_preview_image')) ? $this.parent() : $this; $('
') .width($this.width()) .text($this.attr('data-caption')) .insertAfter($sibling); }); // force all external widget links to open in a new tab/window. // ignore nav widgets which have their own PHP rule for this // // there is a public.config.php option that disables this behavior if (!LW.disable_widget_link_targets) { $region .find('.lw_widget:not(.lw_widget_type_navigation) a[href^="http"]:not([target])').each(function() { var $this = $(this); var url = $this.attr('href'); // add target="_blank" if url is to external site if (!LW.lib.hasCurrentDomainAndTld(url)) { $this.attr('target', '_blank'); } }); } // handle all language toggle elements $('*[class^="lw_language_"]').on('click', function() { var selected_language = $(this).attr('class').split(' ').filter(function(str) { return str.indexOf('lw_language_') === 0; }); selected_language = selected_language.join('').substring(12); if (selected_language) { if (selected_language === 'english') { LW.lib.setCookie(LW.cookie_prefix + 'lang', '', 0, '/', LW.cookie_host, false); } else { var expires = new Date(new Date().setYear(new Date().getFullYear() + 1)); LW.lib.setCookie(LW.cookie_prefix + 'lang', selected_language, expires, '/', LW.cookie_host, false); } location.reload(); } return false; }); // handle data-background-image $('div[data-background-image]').each(function() { // for each data-background-image if (LW.lib.hasWebPSupport()) { // if webp supported by server and browser if ($(this).attr('data-background-image').match(/\.jp[e]*g/)) { // swap in webp for jp(e)g $(this).attr('data-background-image', $(this).attr('data-background-image').replace(/\.jp[e]*g/i, '.webp')); } } $(this).css('background-image', 'url("' + $(this).attr('data-background-image') + '")'); // apply background image $(this).removeAttr('data-background-image'); // remove the data attribute }); }); } }); LW.captcha_requested = false; LW.captcha_loaded = false; $.widget('lw.captcha', { widget_id: null, options: { attachSubmitHandler: true }, _create: function() { var that = this; var $el = this.element; var sitekey = this.sitekey = $el.attr('data-sitekey'); var version = this.version = parseInt($el.attr('data-version')) || 0; var $form = this.$form = $el.closest('form'); var interval_id; // do nothing if the element is not empty if ($.trim($el.html())) return; if (version === 0 || version === 2) { // for Recaptcha 2 interval_id = setInterval(function() { if (LW.captcha_loaded) { clearInterval(interval_id); // initialize Recaptcha that.widget_id = grecaptcha.render($el.get(0), { 'sitekey': sitekey }); $('#g-recaptcha-response').attr('aria-hidden', true).attr('aria-label', 'hidden captcha field'); } }, 50); if (!LW.captcha_requested) { window.lwCaptchaOnloadCallback = function() { LW.captcha_loaded = true; }; $.getScript('http' + (window.location.protocol === 'https:' ? 's' : '') + '://www.google.com/recaptcha/api.js?onload=lwCaptchaOnloadCallback&render=explicit'); LW.captcha_requested = true; } } else if (version === 3) { // else for Recaptcha 3 $el.hide(); // hide the captcha under 3 because it adds whitespace // add handler to call recaptcha's execute method on submit. This method must be called immediately // before submit. Adding this handler is the default but it doesn't work for forms that have their // own submit handler, which is the case for all LW forms module forms and the saveandshare form. // forms with existing submit handlers must call this plugin's execute function if (!$form.hasClass('lw_forms_form') && this.options.attachSubmitHandler === true) { if (LW.captcha_loaded) { this.attachSubmitHandler($form, sitekey); } else { interval_id = setInterval(function() { if (LW.captcha_loaded) { clearInterval(interval_id); that.attachSubmitHandler($form, sitekey); } }, 50); } } if (!LW.captcha_requested) { window.lwCaptchaOnloadCallback = function() { LW.captcha_loaded = true; }; $.getScript('http' + (window.location.protocol === 'https:' ? 's' : '') + '://www.google.com/recaptcha/api.js?onload=lwCaptchaOnloadCallback&render=' + sitekey); LW.captcha_requested = true; } } }, attachSubmitHandler: function($form, sitekey) { // initialize Recaptcha $form.off('submit').on('submit', function(event) { event.preventDefault(); grecaptcha.ready(function() { grecaptcha.execute(sitekey, { action: 'lw_form' }).then(function(token) { $form.find('input[name="token"],input[name="action"]').remove(); $form.prepend(''); $form.prepend(''); $form.unbind('submit').submit(); }); }); }); }, // used by LW forms JS (livewhale/theme/core/scripts/forms.js) execute: function(callback) { var that = this; if (!$.isFunction(callback)) { callback = $.noop; } if (this.version === 3) { grecaptcha.ready(function() { grecaptcha.execute(that.sitekey, { action: 'lw_form' }).then(function(token) { that.$form.find('input[name="token"],input[name="action"]').remove(); that.$form.prepend(''); that.$form.prepend(''); callback(); }); }); } else { callback(); } }, refresh: function() { var version = this.element.attr('data-version'); if (version == '' || version == 2) { grecaptcha.reset(this.widget_id); } }, getWidgetId: function() { return this.widget_id; } }); LW.frontend = { init: function() { this.initSubnavToggle(); this.initPayments(); this.initImagePreview(); if (LW.lib.getCookie(LW.cookie_prefix + 'preview')) { if ($body.hasClass('body_details')) { this.initDetailPreview(); // if lw_preview cookie found, show preview pane on details page } else { LW.lib.setCookie(LW.cookie_prefix + 'preview', '', 0, '/', LW.cookie_host, (window.location.protocol == "https:")); // if not on details page, remove cookie } } // init event detail papge if ($body.hasClass('details_events') || $body.hasClass('body_details')) { this.initEventDetailPage(); } // add aria-current="page" to self-referential links var xpath = 'a[href="'+window.location.href+'"], a[href="'+window.location.pathname+'"]'+(window.location.pathname.substr(window.location.pathname.length - 1)==='/' ? ', a[href="'+window.location.pathname+'/index.php"]' : '')+(window.location.pathname.substr(window.location.pathname.length - 10)==='/index.php' ? ', a[href="'+window.location.pathname.substr(0, window.location.pathname.length - 9)+'"]' : ''); $(xpath).attr('aria-current', 'page'); // add message for hidden content includes if (LW.lib.getQueryStringParam('include_hidden')) { var msg = 'This preview includes hidden content. View with live content only'; $('body').notify({ id: 'lw_preview_message', message: msg, type: 'warning', close_button: false, slideIn: 0 }); } // initialize the frontend behaviors in the entire body region $body.initFrontendRegion(); // init accordions if plugin present if ($.fn.lw_accordion && $('.lw_accordion').length) { $('.lw_accordion').lw_accordion(); } // if url hash refrences an anchor in an accordion, then open the accordion panel and move to it var moveToAnchorInAccordion = function(hash) { var result = false; var $anchor = $(hash); // if targeted anchor is in an accordion content block if ($anchor.length && $anchor.closest('.lw_accordion_block_content').length) { // open accordion panel var $title = $anchor.closest('.lw_accordion_block').find('.lw_accordion_block_title').trigger('click'); // move to anchor after 250 ms delay, accordion animation speed is 200ms setTimeout(function() { $('html,body').animate({ scrollTop: $title.offset().top }, 'fast'); }, 250); result = true; } return result; } if (window.location.hash) { moveToAnchorInAccordion(window.location.hash); } $(window).on('hashchange,popstate', function() { moveToAnchorInAccordion(window.location.hash); }); // randomize widgets if plugin present if ($.fn.randomize && $('.lw_widget_randomized').length) { $('.lw_widget_randomized').randomize(); } // init widget content slideshows if plugin present if ($.fn.contentSlideshow && $('.lw_widget_slideshow').length) { $('.lw_widget_slideshow').contentSlideshow(); } // init pagination if plugin present if ($.fn.paginate && $('.lw_widget_pagination:has(> .lw_paginate)').length) { $('.lw_widget_pagination:has(> .lw_paginate)').paginate(); } // init save-and-share if plugin present if ($.fn.saveandshare && $('.lw_saveandshare_email').length) { $('.lw_saveandshare_email').saveandshare(); } this.initVideo($body); this.initDetailPageMaps(); if (window.location.pathname.indexOf('.test.php') !== -1) { this.showTestingMessage(); } this.addPermalinkHandler(); $('.lw_widget_type_galleries_inline').find('img').attr('loading', 'eager'); // disable lazy loading on inline galleries }, addPermalinkHandler: function() { $body.on('click', '.lw_widget_saveandshare .permalink a', function(e) { e.preventDefault(); var $this = $(this); LW.lib.copyToClipboard(window.location.href); $this.addClass('is-copied'); setTimeout(function() { $this.removeClass('is-copied'); }, 1800); return true; }); }, initVideo: function($wrapper) { // remove width and height attributes from .lw_media if width="100%" var $lw_media = $wrapper.find('.lw_media,.lw_media_wrapper > *:not(.lw_media)').each(function() { var $this = $(this); // reset width and height if width set to 100% if ('100%' === $this.attr('width') || '100%' === $this.css('width')) { $this .removeAttr('width') .removeAttr('height') .css('width', '') .css('height', ''); } // browsers set iframe/object width and height to 300x150 by default - set to 16:9 if (300 === $this.width() && 150 === $this.height()) { // clear width/height style declarations, they override what fitvid sets $this.css('width', ''); $this.css('height', ''); // set 16:9 aspect ratio $this.attr('width', 160); $this.attr('height', 90); } }); $wrapper.fitVids({ ignore: '.lw_media_not_responsive' }); // wrap video with custom dimensions in fluid width wrapper so they shrink with browser $lw_media.filter('.lw_media_not_responsive').each(function() { var $this = $(this); var width = $this.width(); if (!$this.closest('.custom-dimension-video-wrapper').length) { $this .removeAttr('width') .removeAttr('height') .wrap('